﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace MutableTranslator
{
	/// <summary>
	/// Generic class which will search all assemblies in a directory for a defined interface and maintain a list of instances.
	/// </summary>
	/// <typeparam name="T">Interface to discover in assemblies.</typeparam>
	public class PluginManager<T> where T : class
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="PluginManager{T}"/> class.
		/// </summary>
		/// <param name="path">The path to the assemblies.</param>
		public PluginManager(string path)
		{
			Plugins = new List<T>();
			LoadPlugins(path);
		}

		/// <summary>
		/// Gets a collection of instanciated Plugins.
		/// </summary>
		/// <value>
		/// The plugins.
		/// </value>
		public ICollection<T> Plugins { get; private set; }

		private void LoadPlugins(string path)
		{
			if (Directory.Exists(path))
			{
				Plugins.Clear();
				Type pluginType = typeof(T);
				foreach (string dllFile in Directory.GetFiles(path, "*.dll"))
				{
					try
					{
						AssemblyName an = AssemblyName.GetAssemblyName(dllFile);
						Assembly assembly = Assembly.Load(an);
						if (assembly != null)
						{
							foreach (Type type in assembly.GetTypes())
							{
								if (type.IsClass && type.IsPublic && !type.IsAbstract)
								{
									if (type.GetInterface(pluginType.FullName) != null)
									{
										try
										{
											Plugins.Add((T)Activator.CreateInstance(type));
										}
										catch { }
									}
								}
							}
						}
					}
					catch { }
				}
			}
		}
	}
}
